package com.cysion.otbox.ext

import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.cysion.otbox.base.BaseViewModel
import com.cysion.otbox.base.NoViewModel
import com.cysion.otbox.net.ApiAction
import com.cysion.otbox.net.ApiException
import com.cysion.otbox.net.ErrorHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/*
* ViewModel扩展类
* */


/*
*
* ui层将一个任务扔到vm协程里执行
* 该任务最好是耗时操作，一定不能有ui操作
* 可以观察该任务是否成功执行
* 成功执行的话，可以获得任务执行结果
* T:方法返回值的类型，可能有泛型；基本代表了整个json对应的对象
* D，目标数据类型
* */
fun <T:ApiAction,D> BaseViewModel.launchFun(
    task: suspend () -> T,
    onSuccess: suspend (data: D) -> Unit,
    onError: (errCode: String, errMsg: String) -> Unit = { code: String, msg: String ->
        postError(code,msg)
    },
    showLoading: Boolean = false
) {

    if (showLoading) {
        startLoading()
    }
    viewModelScope.launch {
        try {
            val ans = withContext(Dispatchers.IO) {
                task()
            }
            if (ans.isOk) {
                onSuccess(ans.outData() as D)
            } else {
                throw ApiException(ans.outCode(), ans.outMsg())
            }
        } catch (e: java.lang.Exception) {
            val handle = ErrorHandler.handle(e)
            onError(handle.errorCode,handle.errorMsg)
        } finally {
            if (showLoading) {
                stopLoading()
            }
        }
    }
}
fun <T:ApiAction,D> BaseViewModel.launchFun2(
    task: suspend () -> T,
    onError: (errCode: String, errMsg: String) -> Unit = { code: String, msg: String ->
        postError(code,msg)
    },
    showLoading: Boolean = false,
    onSuccess: suspend (data: D) -> Unit,
) {

    if (showLoading) {
        startLoading()
    }
    viewModelScope.launch {
        try {
            val ans = withContext(Dispatchers.IO) {
                task()
            }
            if (ans.isOk) {
                onSuccess(ans.outData() as D)
            } else {
                throw ApiException(ans.outCode(), ans.outMsg())
            }
        } catch (e: java.lang.Exception) {
            val handle = ErrorHandler.handle(e)
            onError(handle.errorCode,handle.errorMsg)
        } finally {
            if (showLoading) {
                stopLoading()
            }
        }
    }
}
class UIViewModel : ViewModel()


/*在主线程启动一个协程，执行需要在主线程进行的可能的ui操作(比如延时操作)
!!!不关心是否正常执行时 使用该方法
其它情况：推荐  BaseViewModel.launchFun
* 当activity销毁时，协程也会自动取消，viewmodel也会自动清理*/
fun AppCompatActivity.launchUI(block: suspend CoroutineScope.() -> Unit) {
    val get = ViewModelProvider(this).get(UIViewModel::class.java)
    get.viewModelScope.launch {
        try {
            block()
        } catch (e: Exception) {
        }
    }
}

/*在主线程启动一个协程，执行需要在主线程进行的可能的ui操作任务(比如延时操作)
!!!不关心是否正常执行时 使用该方法
其它情况：推荐  BaseViewModel.launchFun
* 当fragment销毁时，协程也会自动取消，viewmodel也会自动清理*/
fun Fragment.launchUI(block: suspend CoroutineScope.() -> Unit) {
    val get = ViewModelProvider(this).get(UIViewModel::class.java)
    get.viewModelScope.launch {
        try {
            block()
        } catch (e: Exception) {
        }
    }
}
